////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2012 Kentaro Sekimoto  All rights reserved.
////////////////////////////////////////////////////////////////////////////

#ifndef FM4_I2C_DRIVER_H_
#define FM4_I2C_DRIVER_H_

#include <tinyhal.h>
#include "..\FM4.h"

#define I2C_BPS     400000              // I2C bit rate
#define F_PCLK      (SYSTEM_CLOCK_HZ/2) // Bus clock for the MFS module

// IBCR
#define IBCR_MSS    (1 << 7)    // master/slave selection bit
#define IBCR_ACT    (1 << 6)    // action flag/repeated-start condition bit (ACT for writing/SCC for reading)
#define IBCR_SCC    (1 << 6)    // action flag/repeated-start condition bit (ACT for writing/SCC for reading)
#define IBCR_ACKE   (1 << 5)    // data byte acknowledge bit
#define IBCR_WSEL   (1 << 4)    // wait selection bit
#define IBCR_CNDE   (1 << 3)    // condition detection enable bit
#define IBCR_INTE   (1 << 2)    // interrupt enable bit
#define IBCR_BER    (1 << 1)    // bus error flag bit (1:error detected)
#define IBCR_INT    (1 << 0)    // interrupt flag bit
// IBSR
#define IBSR_FBT    (1 << 7)    // first byte bit
#define IBSR_RACK   (1 << 6)    // acknowledge flag bit
#define IBSR_RSA    (1 << 5)    // reservation detection bit
#define IBSR_TRX    (1 << 4)    // data transfer direction bit
#define IBSR_AL     (1 << 3)    // arbitration lost bit
#define IBSR_RSC    (1 << 2)    // repeated-start condition confirmation bit
#define IBSR_SPC    (1 << 1)    // stop condition confirmation bit
#define IBSR_BB     (1 << 0)    // bus state bit
// SMR
#define SMR_MD2     (1 << 7)    // operation mode bit2
#define SMR_MD1     (1 << 6)    // operation mode bit1
#define SMR_MD0     (1 << 5)    // operation mode bit0
#define SMR_WUCR    (1 << 4)    // wake up control bit
#define SMR_RIE     (1 << 3)    // receive interrupt enable
#define SMR_TIE     (1 << 2)    // transmit interrupt enable

typedef struct {
    union {
        FM4_MFS_TypeDef i2c03;
        FM4_MFS_TypeDef i2c47;
    };
} FM4_MFS_I2C_TypeDef;

typedef void (MFSTX_IRQHandler)(void *param);
typedef void (MFSRX_IRQHandler)(void *param);

struct FM4_I2C_Driver
{
    static const UINT32 c_MaxCh = 8;
    static const UINT8 c_DirectionRead = 1;
    static const UINT8 c_DirectionWrite = 0;
    I2C_HAL_XACTION *m_currentXAction;
    I2C_HAL_XACTION_UNIT *m_currentXActionUnit;
    BOOL m_initialized;

    static BOOL Initialize(UINT32 ch);
    static BOOL Uninitialize(UINT32 ch);
    static void MasterXAction_Start(UINT32 ch, I2C_HAL_XACTION *xAction, bool repeatedStart);
    static void MasterXAction_Stop(UINT32 ch);
    static void GetClockRate(UINT32 ch, UINT32 rateKhz, UINT8& clockRate, UINT8& clockRate2);
    static void GetPins(UINT32 ch, GPIO_PIN& scl, GPIO_PIN& sda);
private:
};

void I2C0RX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C1RX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C2RX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C3RX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C4RX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C5RX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C6RX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C7RX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C0TX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C1TX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C2TX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C3TX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C4TX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C5TX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C6TX_IRQHandler(void *param) __attribute__ ((interrupt));
void I2C7TX_IRQHandler(void *param) __attribute__ ((interrupt));

#endif /* FM4_I2C_DRIVER_H_ */
